﻿using FluentValidation;
using PMS.Data.Entities.Settings;

namespace PMS.Web.Framework.Validators
{
    /// <summary>
    /// Validator extensions
    /// </summary>
    public static class ValidatorExtensions
    {
        /// <summary>
        /// Set decimal validator
        /// </summary>
        /// <typeparam name="TModel">Type of model being validated</typeparam>
        /// <param name="ruleBuilder">Rule builder</param>
        /// <param name="maxValue">Maximum value</param>
        /// <returns>Result</returns>
        public static IRuleBuilderOptions<TModel, decimal> IsDecimal<TModel>(this IRuleBuilder<TModel, decimal> ruleBuilder, decimal maxValue)
        {
            return ruleBuilder.SetValidator(new DecimalPropertyValidator<TModel, decimal>(maxValue));
        }

        /// <summary>
        /// Set username validator
        /// </summary>
        /// <typeparam name="TModel">Type of model being validated</typeparam>
        /// <param name="ruleBuilder">Rule builder</param>
        /// <param name="customerSettings">Customer settings</param>
        /// <returns>Result</returns>
        public static IRuleBuilderOptions<TModel, string> IsUsername<TModel>(this IRuleBuilder<TModel, string> ruleBuilder,
            CustomerSettings customerSettings)
        {
            return ruleBuilder.SetValidator(new UsernamePropertyValidator<TModel, string>(customerSettings));
        }

        /// <summary>
        /// Set phone number validator
        /// </summary>
        /// <typeparam name="TModel">Type of model being validated</typeparam>
        /// <param name="ruleBuilder">Rule builder</param>
        /// <param name="customerSettings">Customer settings</param>
        /// <returns>Result</returns>
        public static IRuleBuilderOptions<TModel, string> IsMobileNumber<TModel>(this IRuleBuilder<TModel, string> ruleBuilder,
            CustomerSettings customerSettings)
        {
            return ruleBuilder.SetValidator(new MobilePhoneValidator<TModel, string>(customerSettings));
        }

        /// <summary>
        /// Implement password validator
        /// </summary>
        /// <typeparam name="TModel">Type of model being validated</typeparam>
        /// <param name="ruleBuilder">Rule builder</param>
        /// <param name="localizationService">Localization service</param>
        /// <param name="customerSettings">Customer settings</param>
        /// <returns>Result</returns>
        public static IRuleBuilder<TModel, string> IsPassword<TModel>(this IRuleBuilder<TModel, string> ruleBuilder, CustomerSettings customerSettings)
        {
            var regExp = "^";
            //Passwords must be at least X characters and contain the following: upper case (A-Z), lower case (a-z), number (0-9) and special character (e.g. !@#$%^&*-)
            regExp += customerSettings.PasswordRequireUppercase ? "(?=.*?[A-Z])" : "";
            regExp += customerSettings.PasswordRequireLowercase ? "(?=.*?[a-z])" : "";
            regExp += customerSettings.PasswordRequireDigit ? "(?=.*?[0-9])" : "";
            regExp += customerSettings.PasswordRequireSpecialCharacter ? "(?=.*?[#?!@$%^&*-])" : "";
            regExp += $".{{{customerSettings.PasswordMinLength},{customerSettings.PasswordMaxLength}}}$";

            var message = string.Format(ValidatorRuleString.Validation_PasswordRule,
                string.Format(ValidatorRuleString.Validation_PasswordLengthValidation, customerSettings.PasswordMinLength, customerSettings.PasswordMaxLength),
                customerSettings.PasswordRequireUppercase ? ValidatorRuleString.Validation_PasswordRequireUppercase : "",
                customerSettings.PasswordRequireLowercase ? ValidatorRuleString.Validation_PasswordRequireLowercase : "",
                customerSettings.PasswordRequireDigit ? ValidatorRuleString.Validation_PasswordRequireDigit : "",
                customerSettings.PasswordRequireSpecialCharacter ? ValidatorRuleString.Validation_PasswordRequireNonAlphanumeric : "");


            var options = ruleBuilder
                .NotEmpty().WithMessage(ValidatorRuleString.Validation_PasswordNotEmpty)
                .Matches(regExp).WithMessage(message.TrimEnd(','));

            return options;
        }
    }

}
